HandlerThread源码分析

HandlerThread是Android系统提供的具有消息循环功能的Thread,这里消息循环理所当然也是基于Looper实现。

我们知道UI线程在启动后会通过Looper的prepareMainLooper方法来为UI线程初始化Looper,然后进入消息循环。而其他非UI线程如果也想具有消息机制,同样能通过Looper的prepare方法为其创建Looper,然后通过loop方法进入消息循环。

继承关系

1
2
3
4
5
6
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
……
}

构造方法

1
2
3
4
5
6
7
8
9
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}

HandlerThread的构造方法只是设置线程名字和优先级,优先级默认为THREAD_PRIORITY_DEFAULT

消息循环

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}

当thread启动后调用run方法,在这里我们通过Looper的prepare方法来为线程创建Looper对象,并保存在Looper的ThreadLocal对象中,在调用loop前可以通过onLooperPrepared方法来做一些准备工作。

使用实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HandlerThread handlerThread = new HandlerThread("myhandlerthread");
handlerThread.start()

//子线程Handler
Handler mHandler = new Handler(handlerThread.getLooper(),new MyCallback());

Handler mUIHandler = new Handler();

class MyCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
//在子线程中进行消息的处理

//通知主线程去更新UI
mUIHandler.sendMessage(msg1);
return false;
}
}

handlerThread启动后,就可以通过其Looper来构造Handler了,这里我们w为Handler提供了CallBack,这样就可以在这个回调中处理消息了,需要注意的是这个回调是在子线程中进行的,如果消息处理完成后需要更新ui仍需要一个UI Handler来进行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Looper getLooper() {
if (!isAlive()) {
return null;
}

// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}

HandlerThread的getLooper方法会等待线程启动后才会真正返回。而没有启动会直接返回null触发异常。

退出消息循环

我们默认的在run方法中调用了Looper的prepare方法,这个方法默认会调用
Looper的如下方法

1
2
3
4
5
6
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}

这个方法的quitAllowed方法为true表示可以推出消息循环,而在UI线程中调用prepareMainLooper方法中默认提供给prepare的值为false表示不允许退出消息循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}

public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}

实际上退出消息循环也是通过looper来完成的,不过最终都是调用MessageQueue的mQueue.quit(true)方法来完成。

坚持原创技术分享,您的支持将鼓励我继续创作!